"""
Some helper functions to help us deal with Django-Webapp templates
"""
######################################################################

# We're overriding Google's default template wrapper for Django
# because it doesn't handle paths the way we want it to -- somewhat
# hackish but it works

from google.appengine.ext.webapp.template import *
# Single underscore names not imported -- get them too
from google.appengine.ext.webapp.template import \
  _swap_settings, _urlnode_render_replacement
  
import os

APP_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PROJECT_ROOT = os.path.dirname(APP_ROOT)
VIEWS_ROOT = os.path.join(APP_ROOT, 'views')

# In order of where we should check for templates first
TEMPLATE_DIRS = (VIEWS_ROOT, APP_ROOT, PROJECT_ROOT)

def render(template_path, template_dict, debug=False):
  """Renders the template at the given path with the given dict of values.

  Identical to overriden version -- we're just redefining it to use our
  different load function
  
  """
  t = load(template_path, debug)
  return t.render(Context(template_dict))

def load(path, debug=False):
  """Loads the Django template from the given path.

  Almost identical to overriden version. This version alters the TEMPLATE_DIRS
  to point to the base directory of this project (assumed to be one level
  down from the directory holding this file)
  
  """
  abspaths = []
  
  if not debug:
    for root in TEMPLATE_DIRS:
      abspath = os.path.abspath(os.path.join(root, path))
      template = template_cache.get(abspath, None)
      if template:
        break
      else:
        abspaths.append(abspath)
  else:
    template = None

  if not template:
    for abspath in abspaths:
      directory, file_name = os.path.split(abspath)
      new_settings = {
        'TEMPLATE_DIRS': (directory,) + TEMPLATE_DIRS,
        'TEMPLATE_DEBUG': debug,
        'DEBUG': debug,
      }
      old_settings = _swap_settings(new_settings)
      try:
        template = django.template.loader.get_template(file_name)
        break
      except django.template.TemplateDoesNotExist:
        pass
      finally:
        _swap_settings(old_settings)
    
    if not template:
      raise django.template.TemplateDoesNotExist('Template not found in %s' % abspaths)
        
    if not debug:
      template_cache[abspath] = template

    def wrap_render(context, orig_render=template.render):
      URLNode = django.template.defaulttags.URLNode
      save_urlnode_render = URLNode.render
      old_settings = _swap_settings(new_settings)
      try:
        URLNode.render = _urlnode_render_replacement
        return orig_render(context)
      finally:
        _swap_settings(old_settings)
        URLNode.render = save_urlnode_render

    template.render = wrap_render

  return template
  
######################################################################

from functools import wraps
from google.appengine.api import users

class RendersTemplate(object):
  """ A decorator for RequestHandler methods to render templates
  
  Decorator accepts strings specifying the location of the template
  Decorated function should return a dict to render template with
  Return None to escape template rendering
  
  """
  def __init__(self, *args):
    self.template_path = os.path.join(*args)
  
  def __call__(self, func):
    """ Rewriting the __call__ method makes class act like function """
    template_path = self.template_path
    
    @wraps(func)
    def _decorated(self, *args, **kwargs):
      template_vars = func(self, *args, **kwargs)
      if not template_vars is None:
        
        # User var is commonly used -- might as well include it
        template_vars.setdefault('user', users.get_current_user())
        
        # Admin var is commonly used
        template_vars.setdefault('admin', users.is_current_user_admin())
        
        # Ditto with flash var
        flash = getattr(self, 'flash', None) or self.request.get('flash')
        if flash:
          template_vars.setdefault('flash', flash)
        
        self.response.out.write(render(
          template_path,
          template_vars))
      
    return _decorated

######################################################################

register_template_library('app.helpers.template_tags')
